#!/usr/bin/env python
# -*- coding:utf-8 -*-
"""
@File   : test08_file_service.py
@Time : 2025/2/21 11:25
@Author: Wangwc
@Describe:  ……
"""
import random
import time

import pytest
import allure

from business.FileServiceApi import FileServiceApi
from utils.login import Login
from commons.logger import log
from utils.config_tools import Config
from commons.fake_data import Fake
from config.path import CERTS_DIR

# TODO 当前模块的配置文件名称，配置在config目录下
config_name = "user.ini"
login = Login(config_name=config_name)
config = Config(config_name=config_name)

#
# @pytest.fixture(scope="function")
# def fileservice_api():
#     """
#     用于初始化FileServiceApi客户端的夹具
#     """
#     login.http_request.update_base_url()
#     token = login.login()
#     api = FileServiceApi(token, configname=config_name)
#     # 动态更新 base_url
#     api.http.update_base_url()
#     return api

global_token = None

@pytest.fixture(scope="function")
def fileservice_api():
    global global_token
    if global_token is None:
        login.http_request.update_base_url()
        global_token = login.login()
    api = FileServiceApi(global_token, configname=config_name)
    # 动态更新 base_url
    api.http.update_base_url()
    return api


def handle_api_call(api_method, *args, attach_to_allure=True, format_result=None, **kwargs):
    if not callable(api_method):
        raise TypeError("api_method 参数必须是可调用对象（如函数或方法）")
    if attach_to_allure is not None and not isinstance(attach_to_allure, bool):
        raise TypeError("attach_to_allure 参数必须是布尔类型或者为 None")
    if format_result is not None and not callable(format_result):
        raise TypeError("format_result 参数必须是可调用对象（如函数）或者为 None")

    max_retries = 3
    for retry in range(max_retries):
        try:
            result = api_method(*args, **kwargs)
            if attach_to_allure:
                if format_result:
                    formatted_result = format_result(result)
                else:
                    formatted_result = str(result)
                allure.attach(formatted_result, f"{api_method.__name__} 调用结果", allure.attachment_type.TEXT)
            log.info(f"{api_method.__name__} 调用成功")
            return result
        except Exception as e:
            allure.attach(str(e), f"{api_method.__name__} 调用错误信息", allure.attachment_type.TEXT)
            log.error(f"{api_method.__name__} 调用出现错误: {e}", exc_info=True)
            # 假设根据错误信息判断 token 过期
            if "token 过期" in str(e) and retry < max_retries - 1:
                global global_token
                global_token = login.login()
                api_method.__self__.token = global_token
                continue
            elif isinstance(e, ConnectionError):
                log.error("连接错误，可能是网络问题，请检查网络连接。")
            elif isinstance(e, ValueError):
                log.error("值错误，可能是传入的参数有误，请检查参数。")
            raise


@allure.feature("控制面板-文件服务")
class TestFileService():
    @allure.title("开启SMB服务")
    def test_start_smb(self, fileservice_api):
        with allure.step("开启smb服务"):
            nasname = config.read_config_ini('device', 'device_name')
            handle_api_call(fileservice_api.start_smb_service, nasname)

        with allure.step("删除samba缓存"):
            handle_api_call(fileservice_api.del_smb_cache)

        with allure.step("确认smb服务开启"):
            results = handle_api_call(fileservice_api.get_smb_config)
            assert results.get('status') == True

    @allure.title("关闭SMB服务")
    def test_stop_smb(self, fileservice_api):
        with allure.step("关闭smb服务"):
            handle_api_call(fileservice_api.stop_smb_service)
            time.sleep(0.5)

        with allure.step("确认smb服务开启"):
            results = handle_api_call(fileservice_api.get_smb_config)
            assert results.get('status') == False

    @allure.title("开启FTPS服务")
    def test_start_ftps(self, fileservice_api):
        with allure.step("开启FTPS服务"):
            handle_api_call(fileservice_api.start_ftp_service, enable_ftps=True)

        with allure.step("确认FTPS服务开启"):
            results = handle_api_call(fileservice_api.get_ftp_config)
            assert results.get('enable_ftps') == True

    @allure.title("关闭FTPS服务")
    def test_stop_ftps(self, fileservice_api):
        with allure.step("关闭FTPS服务"):
            handle_api_call(fileservice_api.stop_ftp_service)

        with allure.step("确认FTPS服务关闭"):
            results = handle_api_call(fileservice_api.get_ftp_config)
            assert results.get('enable_ftps') == False

    @allure.title("自定义FTPS服务端口")
    def test_set_ftps_port(self, fileservice_api):
        with allure.step("校验端口可用"):
            while True:
                ftp_port = random.randint(21, 65535)
                if handle_api_call(fileservice_api.check_port, 'ftp', ftp_port):
                    break

        with allure.step("设置FTPF服务端口"):
            handle_api_call(fileservice_api.start_ftp_service, enable_ftps=True, port=ftp_port)
            time.sleep(0.5)

        with allure.step("确认FTPF服务端口设置成功"):
            results = handle_api_call(fileservice_api.get_ftp_config)
            assert results.get('port') == ftp_port, f"设置FTPS服务端口失败，实际端口为{results.get('port')},期望端口为{ftp_port}"

    @allure.title("开启nfs服务")
    def test_start_nfs(self, fileservice_api):
        with allure.step("开启nfs服务"):
            handle_api_call(fileservice_api.start_nfs_service, enableNfsServer=True)

        with allure.step("确认nfs服务开启"):
            results = handle_api_call(fileservice_api.get_nfs_config)
            assert results.get('enableNfsServer') == True

    @allure.title("关闭nfs服务")
    def test_stop_nfs(self, fileservice_api):
        with allure.step("关闭nfs服务"):
            handle_api_call(fileservice_api.stop_nfs_service)

        with allure.step("确认nfs服务关闭"):
            results = handle_api_call(fileservice_api.get_nfs_config)
            assert results.get('enableNfsServer') == False

    @allure.title("自定义nfs服务端口")
    def test_set_nfs_port(self, fileservice_api):
        with allure.step("校验stat端口可用"):
            while True:
                stat_port = random.randint(21, 65535)
                if handle_api_call(fileservice_api.check_port, 'nfs', stat_port, name='statd'):
                    break

        with allure.step("校验nlockmgr端口可用"):
            while True:
                nlockmgr_port = random.randint(21, 65535)
                if handle_api_call(fileservice_api.check_port, 'nfs', nlockmgr_port, name='nlockmgr'):
                    break

        with allure.step("设置nfs服务端口"):
            handle_api_call(fileservice_api.start_nfs_service, enableNfsServer=True, statport=stat_port,
                            nlockmgrport=nlockmgr_port)
            time.sleep(0.5)

        with allure.step("确认nfs服务端口设置成功"):
            results = handle_api_call(fileservice_api.get_nfs_config)
            assert results.get(
                'statdPort') == stat_port, f"设置nfs服务stat端口失败，实际端口为{results.get('statdPort')},期望端口为{stat_port}"
            assert results.get(
                'nlockMgrPort') == nlockmgr_port, f"设置nfs服务nlockmgr端口失败，实际端口为{results.get('nlockMgrPort')},期望端口为{nlockmgr_port}"

    @allure.title("开启rsync服务")
    def test_start_rsync(self, fileservice_api):
        with allure.step("获取用户信息"):
            results = handle_api_call(fileservice_api.get_user_list)
            user_list = results[0].get('users')
            index = random.randint(0, len(user_list) - 1)
            user_name = user_list[index].get('username')

        with allure.step("准备用户密码"):
            name = config.read_config_ini("user","user_name")
            x_rsa_token = login.verify_check(name)
            raw_passwd = Fake.generate_password()
            passwd = login.data_encrypt.rsa_passwd(x_rsa_token,raw_passwd)

        with allure.step("开启rsync服务"):
            handle_api_call(fileservice_api.start_rsync_service, user_name,password=passwd)

        with allure.step("确认rsync服务开启"):
            results = handle_api_call(fileservice_api.get_rsync_config)
            assert results.get('status') == True

    @allure.title("关闭rsync服务")
    def test_stop_rsync(self, fileservice_api):
        with allure.step("关闭rsync服务"):
            handle_api_call(fileservice_api.stop_rsync_service)

        with allure.step("确认rsync服务关闭"):
            results = handle_api_call(fileservice_api.get_rsync_config)
            assert results.get('status') == False

    @allure.title("自定义rsync服务端口")
    def test_set_rsync_port(self, fileservice_api):
        with allure.step("校验端口可用"):
            while True:
                rsync_port = random.randint(873, 65535)
                if handle_api_call(fileservice_api.check_port, 'rsync', rsync_port):
                    break

        with allure.step("获取用户信息"):
            results = handle_api_call(fileservice_api.get_user_list)
            user_list = results[0].get('users')
            index = random.randint(0, len(user_list) - 1)
            user_name = user_list[index].get('username')

        with allure.step("准备用户密码"):
            name = config.read_config_ini("user", "user_name")
            x_rsa_token = login.verify_check(name)
            raw_passwd = Fake.generate_password()
            passwd = login.data_encrypt.rsa_passwd(x_rsa_token, raw_passwd)

        with allure.step("开启rsync服务"):
            handle_api_call(fileservice_api.start_rsync_service, user_name, password=passwd,port=rsync_port)

        with allure.step("确认rsync服务端口设置成功"):
            results = handle_api_call(fileservice_api.get_rsync_config)
            assert results.get('port') == rsync_port,f"设置rsync服务端口失败，实际端口为{results.get('port')},期望端口为{rsync_port}"

    @allure.title("开启webdav服务")
    def test_start_webdav(self, fileservice_api):
        with allure.step("开启webdav服务"):
            handle_api_call(fileservice_api.start_webdav_service)

        with allure.step("确认webdav服务开启"):
            results = handle_api_call(fileservice_api.get_webdav_config)
            assert results.get('status') == True

    @allure.title("关闭webdav服务")
    def test_stop_webdav(self, fileservice_api):
        with allure.step("关闭webdav服务"):
            handle_api_call(fileservice_api.stop_webdav_service)

        with allure.step("确认webdav服务关闭"):
            results = handle_api_call(fileservice_api.get_webdav_config)
            assert results.get('status') == False

    @allure.title("自定义webdav服务http端口")
    def test_set_webdav_http_port(self, fileservice_api):
        with allure.step("校验端口可用"):
            while True:
                webdav_port = random.randint(5005, 65535)
                if handle_api_call(fileservice_api.check_port, 'webdav', webdav_port):
                    break

        with allure.step("设置webdav服务http端口"):
            handle_api_call(fileservice_api.start_webdav_service,http_port=webdav_port)
            time.sleep(0.5)

        with allure.step("确认webdav服务http端口设置成功"):
            results = handle_api_call(fileservice_api.get_webdav_config)
            assert results.get('http_port') == webdav_port, f"设置webdav服务http端口失败，实际端口为{results.get('http_port')},期望端口为{webdav_port}"

    @allure.title("自定义webdav服务https端口")
    def test_set_webdav_https_port(self, fileservice_api):
        with allure.step("校验端口可用"):
            while True:
                webdav_port = random.randint(5006, 65535)
                if handle_api_call(fileservice_api.check_port, 'webdav', webdav_port):
                    break

        with allure.step("设置webdav服务https端口"):
            handle_api_call(fileservice_api.start_webdav_service, https_port=webdav_port)
            time.sleep(0.5)

        with allure.step("确认webdav服务https端口设置成功"):
            results = handle_api_call(fileservice_api.get_webdav_config)
            assert results.get(
                'https_port') == webdav_port, f"设置webdav服务https端口失败，实际端口为{results.get('https_port')},期望端口为{webdav_port}"

    @allure.title("开启wsdd2服务")
    def test_start_wsdd2(self, fileservice_api):
        with allure.step("获取共享文件夹信息"):
            results = handle_api_call(fileservice_api.get_advanced_config)
            sharedFileInfos = results.get('sharedFileInfos')

        with allure.step("开启wsdd2服务"):
            handle_api_call(fileservice_api.start_advanced_service,sharedFileInfos,enableWsdd2Service=True)
            time.sleep(0.5)

        with allure.step("确认wsdd2服务开启"):
            results = handle_api_call(fileservice_api.get_advanced_config)
            enableWsdd2Service = results.get('enableWsdd2Service')
            assert enableWsdd2Service == True, f"开启wsdd2服务失败，实际状态为{enableWsdd2Service},期望状态为True"

    @allure.title("关闭wsdd2服务")
    def test_stop_wsdd2(self, fileservice_api):
        with allure.step("获取共享文件夹信息"):
            results = handle_api_call(fileservice_api.get_advanced_config)
            sharedFileInfos = results.get('sharedFileInfos')

        with allure.step("关闭wsdd2服务"):
            handle_api_call(fileservice_api.start_advanced_service,sharedFileInfos,enableWsdd2Service=False)

        with allure.step("确认wsdd2服务关闭"):
            results = handle_api_call(fileservice_api.get_advanced_config)
            enableWsdd2Service = results.get('enableWsdd2Service')
            assert enableWsdd2Service == False, f"关闭wsdd2服务失败，实际状态为{enableWsdd2Service},期望状态为False"

    @allure.title("开启Bonjour服务")
    def test_start_Bonjour(self, fileservice_api):
        with allure.step("获取共享文件夹信息"):
            results = handle_api_call(fileservice_api.get_advanced_config)
            sharedFileInfos = results.get('sharedFileInfos')

        with allure.step("开启Bonjour服务"):
            handle_api_call(fileservice_api.start_advanced_service, sharedFileInfos, enableBonjourService=True)
            time.sleep(0.5)

        with allure.step("确认Bonjour服务开启"):
            results = handle_api_call(fileservice_api.get_advanced_config)
            enableBonjourService = results.get('enableBonjourService')
            assert enableBonjourService == True, f"开启Bonjour服务失败，实际状态为{enableBonjourService},期望状态为True"

    @allure.title("关闭Bonjour服务")
    def test_stop_Bonjour(self, fileservice_api):
        with allure.step("获取共享文件夹信息"):
            results = handle_api_call(fileservice_api.get_advanced_config)
            sharedFileInfos = results.get('sharedFileInfos')

        with allure.step("关闭Bonjour服务"):
            handle_api_call(fileservice_api.start_advanced_service, sharedFileInfos, enableBonjourService=False)

        with allure.step("确认Bonjour服务关闭"):
            results = handle_api_call(fileservice_api.get_advanced_config)
            enableBonjourService = results.get('enableBonjourService')
            assert enableBonjourService == False, f"关闭Bonjour服务失败，实际状态为{enableBonjourService},期望状态为False"

    @allure.title("开启UPnP服务")
    def test_start_UPnP(self, fileservice_api):
        with allure.step("获取共享文件夹信息"):
            results = handle_api_call(fileservice_api.get_advanced_config)
            sharedFileInfos = results.get('sharedFileInfos')

        with allure.step("开启UPnP服务"):
            handle_api_call(fileservice_api.start_advanced_service, sharedFileInfos, enableUPnPService=True)
            time.sleep(0.5)

        with allure.step("确认UPnP服务开启"):
            results = handle_api_call(fileservice_api.get_advanced_config)
            enableUPnPService = results.get('enableUPnPService')
            assert enableUPnPService == True, f"开启UPnP服务失败，实际状态为{enableUPnPService},期望状态为True"

    @allure.title("关闭UPnP服务")
    def test_stop_UPnP(self, fileservice_api):
        with allure.step("获取共享文件夹信息"):
            results = handle_api_call(fileservice_api.get_advanced_config)
            sharedFileInfos = results.get('sharedFileInfos')

        with allure.step("关闭UPnP服务"):
            handle_api_call(fileservice_api.start_advanced_service, sharedFileInfos, enableUPnPService=False)

        with allure.step("确认UPnP服务关闭"):
            results = handle_api_call(fileservice_api.get_advanced_config)
            enableUPnPService = results.get('enableUPnPService')
            assert enableUPnPService == False, f"关闭UPnP服务失败，实际状态为{enableUPnPService},期望状态为False"

if __name__ == "__main__":
    pass
